// MyFamily - XML based genealogy program.
// Copyright (C) 2006  Doug Swisher
// See the file COPYING.txt for license details.

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;


namespace DataModel
{
    // Technically speaking, this should really be called FamilyAbstract, but since abstract is a reserved
    // word in C#, it made things cumbersome...
    public class FamilyExtract
    {
        private string id;
        private FamilySource source;
        private List<FamilyPersona> personas = new List<FamilyPersona>();


        public FamilyExtract(string id, FamilySource source)
        {
            this.id = id;
            this.source = source;
        }


        public FamilySource Source
        {
            get { return this.source; }
        }


        public string Id
        {
            get { return this.id; }
        }


        public void AddPersona(FamilyPersona persona)
        {
            this.personas.Add(persona);
        }


        public void SaveXml(XmlWriter writer)
        {
            writer.WriteStartElement("extract");
            writer.WriteAttributeString("id", this.id);
            writer.WriteAttributeString("sourceId", this.source.Id);

            foreach (FamilyPersona persona in this.personas)
            {
                persona.SaveXml(writer);
            }

            writer.WriteEndElement();
        }


        public override bool Equals(object obj)
        {
            // Simple cases...
            if (obj == null)
            {
                return false;
            }

            FamilyExtract other = obj as FamilyExtract;

            if (other == null)
            {
                return false;
            }

            // TODO - Doug - 9/2/2006 - take out the console.writeline calls; they are here to make the
            // unit test failures easier to track down...

            // Check members...
            if (!string.Equals(this.id, other.id))
            {
                Console.WriteLine("FamilyExtract.Equals: !string.Equals(this.id, other.id)...");
                return false;
            }

            if (!string.Equals(this.source.Id, other.source.Id))
            {
                Console.WriteLine("FamilyExtract.Equals: !string.Equals(this.source.Id, other.source.Id)...");
                return false;
            }

            return true;
        }


        public override int GetHashCode()
        {
            // TODO - Doug - 9/2/2006 - do we want to change this implementation at all?
            return base.GetHashCode();
        }


        public void ParseXml(FamilyInfo familyInfo, XmlElement extractElement, LoadResults loadResults)
        {
            foreach (XmlElement elem in extractElement.SelectNodes("*"))
            {
                switch (elem.Name)
                {
                    case "persona":
                        this.LoadPersona(familyInfo, elem, loadResults, this);
                        break;

                    default:
                        loadResults.LogWarning("Unknown extract element '{0}' found when parsing XML.", elem.Name);
                        break;
                }
            }
        }


        // TODO - Doug - 8/29/2006 - move this inside FamilyExtract??
        private void LoadPersona(FamilyInfo familyInfo, XmlElement personaElement, LoadResults loadResults, FamilyExtract extract)
        {
            // Snag the ID and make sure it is valid...
            string id = personaElement.GetAttribute("id");

            if (string.IsNullOrEmpty(id))
            {
                // TODO - Doug - 8/27/2006 - need to get a line number or some other info in here so the user can pinpoint the error...
                loadResults.LogWarning("Persona without ID could not be loaded.");
                return;
            }

            FamilyPersona persona = null;

            if (familyInfo.Personas.ContainsKey(id))
            {
                persona = familyInfo.Personas[id];
            }
            else
            {
                persona = new FamilyPersona(extract, id);
                familyInfo.Personas.Add(id, persona);
            }

            extract.AddPersona(persona);

            persona.ParseXml(familyInfo, personaElement, loadResults);
        }

    }
}
